package knapsack.core;

import genetic.core.Individual;

import java.util.Random;


/**
 * This class represents an individual for solving knapsack problem.
 * 
 * @author vasek
 *
 */
public final class KnapsackIndividual extends Individual {
	
	private int[] chromosome;
	private int[] costs;
	private int[] weights;
	private int capacity;
	
	/**
	 * Constructor.
	 * 
	 * @param configuration knapsack configuration
	 * @param costs price list of things 
	 * @param weights weights of things
	 * @param capacity capacity of knapsack
	 */
	public KnapsackIndividual(int[] configuration, int[] costs, int[] weights, int capacity) {
		this.chromosome = configuration;
		this.costs = costs;
		this.weights = weights;
		this.capacity = capacity;
	}
	
	/**
	 * @return knapsack's configuration.
	 */
	public int[] getChromosome() {
		return chromosome;
	}

	@Override
	public Individual mutate() {
		final Random r = new Random();
		final int index = r.nextInt(chromosome.length);
		
		if (chromosome[index] == 0) {
			chromosome[index] = 1;
		} else {
			chromosome[index] = 0;
		}
		
		return this.clone();
	}

	@Override
	public Individual crossover(Individual other) {
		final Random r = new Random();
		final int index = r.nextInt(chromosome.length);
		final int[] chromosome = this.chromosome.clone();
		
		for (int i = 0; i < index; i++) {
			chromosome[i] = ((KnapsackIndividual) other).getChromosome()[i];
		}
		
		this.chromosome = chromosome;
		
		return this.clone();
	}

	@Override
	protected double evaluate() {
		int fitness = 0;
		int weight = 0;	
		
		for (int i = 0; i < chromosome.length; i++) {
			fitness += (chromosome[i] * costs[i]);
			weight += (chromosome[i] * weights[i]);
		}
		
		if (weight > capacity) {
			fitness = 0;
		}
		
		return fitness;
	}

	@Override
	public boolean isIdeal() {
		return false;
	}

	@Override
	public Individual clone() {		
		KnapsackIndividual clone = (KnapsackIndividual) super.clone();
		
		clone.chromosome = this.chromosome;
		clone.costs = this.costs;
		clone.weights = this.weights;
		
		return clone;
	}

	@Override
	public String toString() {
		return "fitness=" + fitness;
	}	
}
